package top.infopub.mgr.cap.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.infopub.enums.cap.CapProcessDetailTypeEnum;
import top.infopub.enums.fia.IncomeBillTypeEnum;
import top.infopub.enums.fia.IncomeSettlementModeEnum;
import top.infopub.enums.fia.PayBillTypeEnum;
import top.infopub.enums.mkt.ProProcesssStatusEnum;
import top.infopub.mgr.cap.dao.*;
import top.infopub.mgr.cap.domain.CapHisProcessDomain;
import top.infopub.mgr.cap.service.CapProcessManageService;
import top.infopub.mgr.cap.service.InformationSubmitApprovalService;
import top.infopub.mgr.cap.vo.LoanFinVo;
import top.infopub.mgr.common.page.ParamPage;
import top.infopub.mgr.exception.FlowProcessException;
import top.infopub.mgr.fia.service.IncomeBillService;
import top.infopub.mgr.fia.service.PayBillService;
import top.infopub.mgr.flow.cnst.FlowTemplateEnum;
import top.infopub.mgr.flow.service.*;
import top.infopub.mgr.hr.dao.PostGroupDao;
import top.infopub.mgr.mkt.dao.ProjectInfoDao;
import top.infopub.mgr.sys.service.OperatorService;
import top.infopub.model.cap.*;
import top.infopub.model.fia.IncomeBill;
import top.infopub.model.fia.PayBill;
import top.infopub.model.flow.Process;
import top.infopub.model.flow.ProcessNode;
import top.infopub.model.flow.Template;
import top.infopub.model.flow.TemplateNode;
import top.infopub.model.hr.PostGroup;
import top.infopub.model.mkt.ProjectInfo;
import top.infopub.model.sys.Operator;
import top.infopub.security.util.SessionUserUtils;
import top.infopub.security.vo.AuthorizationVO;
import top.infopub.tdp.util.BizParaUtil;
import top.infopub.util.IdFactory;
import top.infopub.util.UtilTools;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class CapProcessManageServiceImpl implements CapProcessManageService {
    @Autowired
    private CapProcessDetailDao capProcessDetailDao;

    @Lazy
    @Autowired
    private WsFlowProcessService wsFlowProcess;

    @Autowired
    private ProcessService processService;

    @Autowired
    private TemplateService templateService;

    @Autowired
    private TemplateNodeService templateNodeService;

    @Autowired
    private ProcessNodeService processNodeService;

    @Lazy
    @Autowired
    private WsFlowProcessService wsFlowProcessService;

    @Autowired
    private OperatorService operatorService;

    @Autowired
    private ProjectInfoDao projectInfoDao;

    @Autowired
    private SetupFinDao setupFinDao;

    @Lazy
    @Autowired
    private OAFlowService oaFlowService;

    @Autowired
    private ContractReviewDao contractReviewDao;

    @Autowired
    private InformationSubmitApprovalDao informationSubmitApprovalDao;

    @Autowired
    private PostGroupDao postGroupDao;

    @Lazy
    @Autowired
    private InformationSubmitApprovalService informationSubmitApprovalService;

    @Autowired
    private LoanFinDao loanFinDao;

    @Lazy
    @Autowired
    private IncomeBillService incomeBillService;

    @Lazy
    @Autowired
    private PayBillService payBillService;

    @Autowired
    private FinanceReimbursementDao financeReimbursementDao;

    @Autowired
    private PayInterestDao payInterestDao;

    @Autowired
    private PayfeeApplyDao payfeeApplyDao;

    @Autowired
    private PayfeeApplyDetailDao payfeeApplyDetailDao;

    @Override
    @Transactional
    public String sendProcess(CapProcessDetailTypeEnum cpdt, String detailJson, String bizSguid, String proCode, AuthorizationVO vo) {
        ProjectInfo proInfo = projectInfoDao.findByProCode(proCode);
        SetupFin setupFin = setupFinDao.queryByProCode(proCode);
        if (proInfo == null && setupFin == null) {
            throw new FlowProcessException("项目数据不存在~~");
        }
        String proName = null;
        if (proInfo != null && StringUtils.isNotBlank(proInfo.getProName())) proName = proInfo.getProName();
        if (setupFin != null && StringUtils.isNotBlank(setupFin.getProName())) proName = setupFin.getProName();
        String processId = IdFactory.getUUIDUpper();
        //保存当前详细数据json格式
        CapProcessDetail cpd = new CapProcessDetail();
        cpd.setBizSguid(bizSguid);
        cpd.setProCode(proCode);
        cpd.setFlowNode(cpdt.getNode());
        cpd.setProcessStatus("1");
        cpd.setDetailJson(detailJson);
        cpd.setAddBy(vo.getId());
        cpd.setAddTime(new Date());
        cpd.setProcessId(processId);
        capProcessDetailDao.insert(cpd);
        //待办标题
        StringBuffer oaTitle = new StringBuffer();
        oaTitle.append(proName);
        oaTitle.append("-");
        oaTitle.append(cpdt.getNodeName());
        // 注意 这里根据不同的业务分支判断条件 获得不同enum
        FlowTemplateEnum templateEnum = getByCapProcessNode(cpdt);
        //根据表名更新对应业务表的流程ID和流程状态
        capProcessDetailDao.modifyProcessStatusBySguid(templateEnum.getSrcBizTable(), ProProcesssStatusEnum.PRO_STATUS1.getCode(), processId, bizSguid);
        //如果是资料报审审批，修改子表-融资报审表状态
        if (StringUtils.equals(CapProcessDetailTypeEnum.PRO_NODE_TYPE5.getNode(), cpd.getFlowNode())) {
            capProcessDetailDao.modifyFinancingApproval(ProProcesssStatusEnum.PRO_STATUS1.getCode(), cpd.getProCode(), ProProcesssStatusEnum.PRO_STATUS10.getCode());
        }
        // 处理工作流数据
        wsFlowProcess.launch(templateEnum, bizSguid, processId, oaTitle.toString());
        return processId;
    }

    private FlowTemplateEnum getByCapProcessNode(CapProcessDetailTypeEnum cpdt) {
        if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE1.getNode())) {
            //授信管理
            return FlowTemplateEnum.CAP_CREDIT_BALANCE;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE2.getNode())) {
            //融资初调--预立项审批通过发送待办
            return FlowTemplateEnum.CAP_LOOK_INFO_BEGIN;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE3.getNode())) {
            //融资尽调--市场项目立项并且融资初调授信余额满足
            return FlowTemplateEnum.CAP_LOOK_INFO;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE4.getNode())) {
            //融资立项--尽调审批通过自动发待办，新增融资立项和前面无关联
            return FlowTemplateEnum.CAP_SETUP_FIN;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE5.getNode())) {
            //资料报审
            return FlowTemplateEnum.CAP_SUBMIT_APPROVAL;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE6.getNode())) {
            //融资跟踪
            return FlowTemplateEnum.CAP_FINANCING_TRACKING;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE7.getNode())) {
            //金融批复--提交后进入金融机构选择
            return FlowTemplateEnum.CAP_FUNDING_APPROVAL;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE8.getNode())) {
            //金融机构选择
            return FlowTemplateEnum.CAP_FINANCIAL_INSTITUTIONS;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE9.getNode())) {
            //借款合同
            return FlowTemplateEnum.CAP_LOAN_CONTRACT;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE10.getNode())) {
            //保证合同
            return FlowTemplateEnum.CAP_CONTRACT_GUARANTY;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE11.getNode())) {
            //质押合同
            return FlowTemplateEnum.CAP_CONTRACT_PLEDGE;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE12.getNode())) {
            //抵押合同
            return FlowTemplateEnum.CAP_CONTRACT_MORTGAGE;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE13.getNode())) {
            //合同评审--8、9、10、11其中一条审批通过进入合同评审
            return FlowTemplateEnum.CAP_CONTRACT_REVIEW;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE14.getNode())) {
            //还款计划
            return FlowTemplateEnum.CAP_REPAYMENT_SCHEDULE;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE15.getNode())) {
            //融资方案
            return FlowTemplateEnum.CAP_FINANCING_PLAN;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE16.getNode())) {
            //融资放款
            return FlowTemplateEnum.CAP_LOAN_FIN;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE17.getNode())) {
            //融资还款
            return FlowTemplateEnum.CAP_FINANCE_REIMBURSEMENT;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE18.getNode())) {
            //融资付息
            return FlowTemplateEnum.CAP_PAY_INTEREST;
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE19.getNode())) {
            //融资付费申请-小于1亿
            return FlowTemplateEnum.CAP_PAYFEE_APPLY;
        }
        return null;
    }

    @Override
    @Transactional
    public void auditProject(String bizSguid, String processId, String status, String auditMsg) {
        Process proc = processService.selectByPrimaryKey(processId);
        if (proc == null) {
            throw new FlowProcessException("获取不到对应的审批主数据~~");
        }
        CapProcessDetail cpd = capProcessDetailDao.queryByProcessId(processId);
        if (cpd == null) {
            throw new FlowProcessException("发起审批业务数据不存在~~");
        }
        bizSguid = cpd.getBizSguid();
        ProjectInfo proInfo = projectInfoDao.findByProCode(cpd.getProCode());
        SetupFin setupFin = setupFinDao.queryByProCode(cpd.getProCode());
        if (proInfo == null && setupFin == null) {
            throw new FlowProcessException("项目数据不存在~~");
        }
        String proName = null;
        if (proInfo != null && StringUtils.isNotBlank(proInfo.getProName())) proName = proInfo.getProName();
        if (setupFin != null && StringUtils.isNotBlank(setupFin.getProName())) proName = setupFin.getProName();
        // 当前索引
        Integer nowIdx = proc.getNowIdx();
        // 模板ID
        String templateId = proc.getTemplateId();
        // 获得关联业务表名
        String srcBizTable = proc.getSrcBizTable();
        AuthorizationVO vo = SessionUserUtils.getSessionAttributeForUserDtl();
        // 操作人ID
        String userId = vo.getId();
        // 操作人姓名
        String realName = vo.getRealName();
        //待办标题
        StringBuffer oaTitle = new StringBuffer();
        oaTitle.append(proName);
        oaTitle.append("-");
        CapProcessDetailTypeEnum cpdt = CapProcessDetailTypeEnum.getByNode(cpd.getFlowNode());
        if (cpdt != null) {
            oaTitle.append(cpdt.getNodeName());
        }

        Template queryTemplate = new Template();
        queryTemplate.setId(templateId);
        queryTemplate.setIsUsable("1");// 可用
        List<Template> templates = templateService.selectByEntityWhere(queryTemplate);
        if (templates == null || templates.size() < 1) {
            throw new FlowProcessException("获取不到对应的工作流模板数据~");
        }
        // 查询当前模板剩余的【审批】节点信息 nodex>nowIdx 按照节点索引正序 (不查询[知会]节点)
        List<TemplateNode> templateNodeList = templateNodeService.queryRestNodes(templateId,nowIdx);
        if (templateNodeList == null) {
            throw new FlowProcessException("获取不到对应的工作流节点数据~");
        }

        // 【重要】特殊处理，融资-立项的 副总有最终审批权， [轮到副总审批时]，移除最后的董事长node，使副总作为最后节点
        TemplateNode capSetupFinLast = new TemplateNode();
        if (srcBizTable.equalsIgnoreCase("CAP_SETUP_FIN")) {
            String triggerNodeIdx = BizParaUtil.get("flow_cap_setup_fin_trigger");
            Integer triggerNodeIdxInt = Integer.valueOf(triggerNodeIdx);
            if (nowIdx.equals(triggerNodeIdxInt)) {
                capSetupFinLast = templateNodeList.get(templateNodeList.size() - 1);
                templateNodeList.remove(templateNodeList.size() - 1);
            }
        }

        ProcessNode nowProcNode = new ProcessNode();
        // 非最后一步审核
        if (templateNodeList.size() > 0) {
            // 查询当前审批流程节点
            ProcessNode procNodeWhere = new ProcessNode();
            procNodeWhere.setProcessId(processId);
            procNodeWhere.setNodeIdx(nowIdx);
            procNodeWhere.setState("-1"); // 未审批
            procNodeWhere.setDealUserId(userId);// 审批人为当前操作人
            List<ProcessNode> queryProcessNodes = processNodeService.selectByEntityWhere(procNodeWhere);
            if (queryProcessNodes == null || queryProcessNodes.size() < 1) {
                throw new FlowProcessException("获取不到有效的审批节点数据~");
            }
            // 处理当前审批节点数据
            nowProcNode = queryProcessNodes.get(0);

            //OA待办处理
            if(StringUtils.isNotEmpty(nowProcNode.getOaId())){
                String oaId = nowProcNode.getOaId();
                boolean finishOA = oaFlowService.finishOA(oaId);
                if(finishOA){
                    nowProcNode.setOaFinish(0);
                }else{
                    throw new FlowProcessException("处理OA待办失败，请联系管理员");
                }
            }

            nowProcNode.setDealName(realName);
            nowProcNode.setDealTime(new Date());
            nowProcNode.setState(status);
            nowProcNode.setDealIdea(auditMsg);
            nowProcNode.setUserOrgId(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgId")));
            nowProcNode.setUserOrgName(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgName")));
            nowProcNode.setUserDeptId(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptId")));
            nowProcNode.setUserDeptName(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptName")));
            processNodeService.updateByPrimaryKey(nowProcNode);

            //如果是会签，则查询会签是否全部通过
            boolean huiQianFlag = true;
            List<ProcessNode> huiQianProcessNodes = null;
            if(nowProcNode.getNodePolicy() == 3){
                ProcessNode hqNode = new ProcessNode();
                hqNode.setProcessId(processId);
                hqNode.setNodeIdx(nowIdx);
                huiQianProcessNodes = processNodeService.selectByEntityWhere(hqNode);
                for (ProcessNode huiQianProcessNode : huiQianProcessNodes) {
                    if(!"1".equals(huiQianProcessNode.getState())){
                        huiQianFlag = false;
                        break;
                    }
                }
            }

            //审批通过
            if (StringUtils.equals("1", status)) {
                if(huiQianFlag) {
                    //判断下个节点是否为--处理中间的知会节点
                    notifyProcess(templateId, nowIdx, processId, srcBizTable, bizSguid);
                    // 下一步的模板节点
                    TemplateNode nextNode = templateNodeList.get(0);
                    List<TemplateNode> nextTemplateNode = new ArrayList<>();
                    for (TemplateNode node : templateNodeList) {
                        if (nextNode.getNodeIdx() == node.getNodeIdx()) {
                            nextTemplateNode.add(node);
                        }
                    }
                    for (TemplateNode templateNode : nextTemplateNode) {
                        List<String> checkUserIds = wsFlowProcessService.checkUserIds(templateNode.getId(), processId);
                        //String tempCheckUserId = checkUserIds(templateNode.getId());
                        for (String tempCheckUserId : checkUserIds) {
                            //发起OA待办
                            String oaId = oaFlowService.sendOAToDo(oaTitle.toString(), SessionUserUtils.getSessionUserId(), tempCheckUserId, srcBizTable, bizSguid);

                            ProcessNode node_next = new ProcessNode();
                            node_next.setAddTime(new Date());
                            node_next.setProcessId(processId);
                            node_next.setNodeIdx(templateNode.getNodeIdx());
                            node_next.setNodeName(templateNode.getNodeName());
                            node_next.setNodePolicy(templateNode.getNodePolicy());// 权限 审批
                            node_next.setDealUserId(tempCheckUserId);// 处理人取模板中的审核人
                            node_next.setDealName(dealNameOf(tempCheckUserId).getSrealName());// 增加处理人姓名
                            node_next.setState("-1");// 节点的审批状态为初始-待审批
                            node_next.setSrcBizTable(srcBizTable);
                            node_next.setSrcBizSguid(bizSguid);
                            node_next.setOaId(oaId);
                            processNodeService.insert(node_next);
                            // 更新审批流程信息
                            proc.setNowIdx(templateNode.getNodeIdx());
                            proc.setMaxIdx(templateNodeList.get(templateNodeList.size() - 1).getNodeIdx());// 再次更新最大索引
                            processService.updateByPrimaryKey(proc);
                        }
                    }
                }
            } else {
                //审批不通过
                proc.setEndTime(new Date());
                proc.setProcessStatus(ProProcesssStatusEnum.PRO_STATUS10.getCode()); // 10=审批终止
                proc.setIsFeedback("0");
                processService.updateByPrimaryKey(proc);
                // 原业务表审批状态 修改为审批终止
                capProcessDetailDao.modifyProcessStatusBySguid(srcBizTable, ProProcesssStatusEnum.PRO_STATUS10.getCode(), null, bizSguid);
                //如果是资料报审审批，修改子表-融资报审表状态
                if (StringUtils.equals(CapProcessDetailTypeEnum.PRO_NODE_TYPE5.getNode(), cpd.getFlowNode())) {
                    capProcessDetailDao.modifyFinancingApproval(ProProcesssStatusEnum.PRO_STATUS10.getCode(), cpd.getProCode(), ProProcesssStatusEnum.PRO_STATUS1.getCode());
                }
                //修改项目流程明细表状态
                capProcessDetailDao.modifyProcessStatus(ProProcesssStatusEnum.PRO_STATUS10.getCode(), processId);
                //审批不通过需要撤销所有还未审批的会签节点待办
                if (huiQianProcessNodes != null && huiQianProcessNodes.size() > 0) {
                    for (ProcessNode huiQianProcessNode : huiQianProcessNodes) {
                        if("-1".equals(huiQianProcessNode.getState())){
                            oaFlowService.finishOA(huiQianProcessNode.getOaId());
                        }
                    }
                }
            }
        } else {
            //最后一步审核节点
            // 查询当前审批流程节点
            ProcessNode procNodeWhere = new ProcessNode();
            procNodeWhere.setProcessId(processId);
            procNodeWhere.setNodeIdx(nowIdx);
            procNodeWhere.setState("-1"); // 未审批
            procNodeWhere.setDealUserId(userId);// 审批人为当前操作人
            List<ProcessNode> queryProcessNodes = processNodeService.selectByEntityWhere(procNodeWhere);
            if (queryProcessNodes == null || queryProcessNodes.size() < 1) {
                throw new FlowProcessException("获取不到对应的审批节点数据~");
            }
            // 处理当前审批节点数据
            nowProcNode = queryProcessNodes.get(0);

            //OA待办处理
            if(StringUtils.isNotEmpty(nowProcNode.getOaId())){
                String oaId = nowProcNode.getOaId();
                boolean finishOA = oaFlowService.finishOA(oaId);
                if(finishOA){
                    nowProcNode.setOaFinish(0);
                }else{
//                    throw new FlowProcessException("处理OA待办失败，请联系管理员");
                }
            }

            nowProcNode.setDealName(realName);
            nowProcNode.setDealTime(new Date());
            nowProcNode.setState(status);
            nowProcNode.setDealIdea(auditMsg);
            nowProcNode.setUserOrgId(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgId")));
            nowProcNode.setUserOrgName(String.valueOf(SessionUserUtils.getSessionAttribute("bindOrgName")));
            nowProcNode.setUserDeptId(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptId")));
            nowProcNode.setUserDeptName(String.valueOf(SessionUserUtils.getSessionAttribute("bindDeptName")));
            processNodeService.updateByPrimaryKey(nowProcNode);

            //如果是会签，则查询会签是否全部通过
            boolean huiQianFlag = true;
            List<ProcessNode> huiQianProcessNodes = null;
            if(nowProcNode.getNodePolicy() == 3){
                ProcessNode hqNode = new ProcessNode();
                hqNode.setProcessId(processId);
                hqNode.setNodeIdx(nowIdx);
                huiQianProcessNodes = processNodeService.selectByEntityWhere(hqNode);
                for (ProcessNode huiQianProcessNode : huiQianProcessNodes) {
                    if(!"1".equals(huiQianProcessNode.getState())){
                        huiQianFlag = false;
                        break;
                    }
                }
            }

            //审核通过
            if (StringUtils.equals("1", status)) {
                // 更新审批流程信息
                if (huiQianFlag) {
                    proc.setEndTime(new Date());
                    proc.setProcessStatus(ProProcesssStatusEnum.PRO_STATUS9.getCode()); // 9=审批完成
                    proc.setIsFeedback("0");
                    processService.updateByPrimaryKey(proc);
                    // 原业务表审批状态 修改审批状态
                    capProcessDetailDao.modifyProcessStatusBySguid(srcBizTable, ProProcesssStatusEnum.PRO_STATUS9.getCode(), null, bizSguid);
                    //如果是资料报审审批，修改子表-融资报审表状态
                    if (StringUtils.equals(CapProcessDetailTypeEnum.PRO_NODE_TYPE5.getNode(), cpd.getFlowNode())) {
                        capProcessDetailDao.modifyFinancingApproval(ProProcesssStatusEnum.PRO_STATUS9.getCode(), cpd.getProCode(), ProProcesssStatusEnum.PRO_STATUS1.getCode());
                    }
                    //修改项目流程明细表状态
                    capProcessDetailDao.modifyProcessStatus(ProProcesssStatusEnum.PRO_STATUS9.getCode(), processId);

                    // 所有【审核】节点都通过时， 最后统一生成 后续的【知会】节点
                    List<TemplateNode> toNotifyList = templateNodeService.queryRestNotifyNodes(templateId, nowIdx);
                    for (TemplateNode var : toNotifyList) {
                        List<String> strings = wsFlowProcessService.checkUserIds(var.getId(), processId);
                        for (String string : strings) {
                            ProcessNode node_next = new ProcessNode();
                            node_next.setDealUserId(string);// 处理人取模板中的审核人
                            node_next.setAddTime(new Date());
                            node_next.setProcessId(processId);
                            node_next.setNodeIdx(var.getNodeIdx());
                            node_next.setNodeName(var.getNodeName());
                            node_next.setNodePolicy(2);// 权限 知会
                            node_next.setState("1");// 节点的审批状态为-我已同意
                            node_next.setSrcBizTable(srcBizTable);
                            node_next.setSrcBizSguid(bizSguid);
                            processNodeService.insert(node_next);
                        }
                    }

                    //融资管理-新增下一个业务表数据
                    autoNextBizTableData(cpd, vo, bizSguid, srcBizTable, proName);
                }
            } else {
                proc.setEndTime(new Date());
                proc.setProcessStatus(ProProcesssStatusEnum.PRO_STATUS10.getCode()); // 10=审批终止
                proc.setIsFeedback("0");
                processService.updateByPrimaryKey(proc);
                // 原业务表审批状态 修改为审批终止
                capProcessDetailDao.modifyProcessStatusBySguid(srcBizTable, ProProcesssStatusEnum.PRO_STATUS10.getCode(), null, bizSguid);
                //如果是资料报审审批，修改子表-融资报审表状态
                if (StringUtils.equals(CapProcessDetailTypeEnum.PRO_NODE_TYPE5.getNode(), cpd.getFlowNode())) {
                    capProcessDetailDao.modifyFinancingApproval(ProProcesssStatusEnum.PRO_STATUS10.getCode(), cpd.getProCode(), ProProcesssStatusEnum.PRO_STATUS1.getCode());
                }
                //修改项目流程明细表状态
                capProcessDetailDao.modifyProcessStatus(ProProcesssStatusEnum.PRO_STATUS10.getCode(), processId);

                //审批不通过需要撤销所有还未审批的会签节点待办
                if (huiQianProcessNodes != null && huiQianProcessNodes.size() > 0) {
                    for (ProcessNode huiQianProcessNode : huiQianProcessNodes) {
                        if("-1".equals(huiQianProcessNode.getState())){
                            oaFlowService.finishOA(huiQianProcessNode.getOaId());
                        }
                    }
                }

                // 【重要】特殊处理，融资-立项的 副总审批拒绝，但是董事长可以继续审批  开始
                if (srcBizTable.equalsIgnoreCase("CAP_SETUP_FIN")) {
                    String triggerNodeIdx = BizParaUtil.get("flow_cap_setup_fin_trigger");
                    if (org.apache.commons.lang.StringUtils.isNotBlank(triggerNodeIdx)) {
                        if (org.apache.commons.lang.StringUtils.equals(nowProcNode.getNodeIdx().toString(), triggerNodeIdx)) {
                            // 董事长模板节点
                            ProcessNode node_next = new ProcessNode();
                            node_next.setAddTime(new Date());
                            node_next.setProcessId(processId);
                            node_next.setNodeIdx(capSetupFinLast.getNodeIdx());
                            node_next.setNodeName(capSetupFinLast.getNodeName());
                            node_next.setNodePolicy(capSetupFinLast.getNodePolicy());// 董事长-权限
                            String tempCheckUserId = wsFlowProcessService.checkUserId(capSetupFinLast.getId());
                            node_next.setDealUserId(tempCheckUserId);// 处理人取模板中的审核人
                            node_next.setDealName(dealNameOf(tempCheckUserId).getSrealName());// 增加处理人姓名
                            node_next.setState("-1");// 节点的审批状态为初始-待审批
                            node_next.setSrcBizTable(srcBizTable);
                            node_next.setSrcBizSguid(bizSguid);
                            processNodeService.insert(node_next);
                            // 更新审批流程信息
                            proc.setNowIdx(capSetupFinLast.getNodeIdx());
                            processService.updateByPrimaryKey(proc);
                        }
                    }
                }// 融资-立项的 副总审批拒绝，但是董事长可以继续审批  结束
            }
        }
    }

    /**
     * 市场管理-审核通过新增下个节点主表数据
     * @param vo
     * @param bizSguid
     */
    public void autoNextBizTableData(CapProcessDetail cpd, AuthorizationVO vo, String bizSguid, String srcBizTable, String proName) {
        CapProcessDetailTypeEnum cpdt = CapProcessDetailTypeEnum.getByNode(cpd.getFlowNode());
        if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE1.getNode())) {
            //授信管理审批通过--无后续操作【可能没有审批】
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE2.getNode())) {
            //融资初调审批通过--融资尽调，市场项目立项审批通过并且融资初调授信余额满足【融资初调可能没有审批，初调满足直接到尽调】
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE3.getNode())) {
            //融资尽调审批通过--往融资立项主表写入数据并发OA待办，新增融资立项和前面无关联
            ProjectInfo proInfo = projectInfoDao.findByProCode(cpd.getProCode());
            if (proInfo == null) {
                throw new FlowProcessException("项目数据不存在~");
            }

            //新增融资立项主表数据
            SetupFin setupFin = new SetupFin();
            setupFin.setCodes(IdFactory.getUUIDUpper());
            setupFin.setProCode(cpd.getProCode());
            setupFin.setProName(proName);
            setupFin.setAddBy(proInfo.getAddBy());
            setupFin.setAddTime(new Date());
            setupFin.setUptBy(vo.getId());
            setupFin.setUptTime(new Date());
            setupFinDao.insertByProcess(setupFin);

            //给营销经理发送OA待办
            String oaTitle = UtilTools.getCapOaTitle(proName, CapProcessDetailTypeEnum.PRO_NODE_TYPE4);
            String oaId = oaFlowService.sendOAToDo(oaTitle, vo.getId(), proInfo.getAddBy(), FlowTemplateEnum.CAP_SETUP_FIN.getSrcBizTable(), setupFin.getId());
            if (StringUtils.isNotBlank(oaId)) {
                capProcessDetailDao.modifyOaIdById(FlowTemplateEnum.CAP_SETUP_FIN.getSrcBizTable(), oaId, setupFin.getId());
            }
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE4.getNode())) {
            //融资立项审批通过--往资料报审主表写入数据
            InformationSubmitApproval isa = new InformationSubmitApproval();
            isa.setCodes(IdFactory.getUUIDUpper());
            isa.setProCode(cpd.getProCode());
            isa.setAddBy(vo.getId());
            isa.setAddTime(new Date());
            isa.setUptBy(vo.getId());
            isa.setUptTime(new Date());
            isa.setProName(proName);
            informationSubmitApprovalDao.insertByProcess(isa);
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE5.getNode())) {
            //资料报审审批通过--往融资批复主表写入数据
            ProjectInfo proInfo = projectInfoDao.findByProCode(cpd.getProCode());
            SetupFin setupFin = setupFinDao.queryByProCode(cpd.getProCode());
            if (proInfo == null && setupFin == null) {
                throw new FlowProcessException("项目数据不存在~~");
            }
            String toUserId = null;
            if (proInfo != null && StringUtils.isNotBlank(proInfo.getAddBy())) toUserId = proInfo.getAddBy();
            if (setupFin != null && StringUtils.isNotBlank(setupFin.getAddBy())) toUserId = setupFin.getAddBy();
            List<String> ids = informationSubmitApprovalService.saveFundingApproval(cpd.getProCode(), vo);
            //给营销经理发送OA待办
            for (String id : ids) {
                String oaTitle = UtilTools.getCapOaTitle(proName, CapProcessDetailTypeEnum.PRO_NODE_TYPE7);
                String oaId = oaFlowService.sendOAToDo(oaTitle, vo.getId(), toUserId, FlowTemplateEnum.CAP_FUNDING_APPROVAL.getSrcBizTable(), id);
                if (StringUtils.isNotBlank(oaId)) {
                    capProcessDetailDao.modifyOaIdById(FlowTemplateEnum.CAP_FUNDING_APPROVAL.getSrcBizTable(), oaId, id);
                }
            }
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE6.getNode())) {
            //融资跟踪审批通过--无操作
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE7.getNode())) {
            //金融批复审批通过--无操作--可以循环审批--提交后进入金融机构选择【金融批复提交的时候需要往金融机构选择主表写入数据】
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE8.getNode())) {
            //金融机构选择审批通过--无操作
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE9.getNode())) {
            //借款合同审批通过--往合同审批中新增数据(同PRO_CODE只有一条记录)并发送OA待办
            handleContractReviewData(cpd, vo, proName);
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE10.getNode())) {
            //保证合同审批通过--往合同审批中新增数据(同PRO_CODE只有一条记录)并发送OA待办
            handleContractReviewData(cpd, vo, proName);
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE11.getNode())) {
            //质押合同审批通过--往合同审批中新增数据(同PRO_CODE只有一条记录)并发送OA待办
            handleContractReviewData(cpd, vo, proName);
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE12.getNode())) {
            //抵押合同审批通过--往合同审批中新增数据(同PRO_CODE只有一条记录)并发送OA待办
            handleContractReviewData(cpd, vo, proName);
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE13.getNode())) {
            //合同评审审批通过--合同评审支持循环评审--无操作
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE14.getNode())) {
            //还款计划审批通过--无操作
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE15.getNode())) {
            //融资方案审批通过--无操作
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE16.getNode())) {
            //融资放款审批通过--财务模块-收款登记-新增主表数据
            savePayOrIncomeBill(cpd.getProCode(), bizSguid, srcBizTable);
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE17.getNode())) {
            //融资还款审批通过--财务模块-资金支付-新增主表数据
            savePayOrIncomeBill(cpd.getProCode(), bizSguid, srcBizTable);
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE18.getNode())) {
            //融资付息审批通过--财务模块-资金支付-新增主表数据
            savePayOrIncomeBill(cpd.getProCode(), bizSguid, srcBizTable);
        } else if (StringUtils.equals(cpdt.getNode(), CapProcessDetailTypeEnum.PRO_NODE_TYPE19.getNode())) {
            //融资付费申请审批通过--财务模块-资金支付-新增主表数据
            savePayOrIncomeBill(cpd.getProCode(), bizSguid, srcBizTable);
        }
    }

    public void handleContractReviewData(CapProcessDetail cpd, AuthorizationVO vo, String proName) {
        ContractReview tmpCr = contractReviewDao.queryByProCode(cpd.getProCode());
        if (tmpCr == null) {
            SetupFin setupFin = setupFinDao.queryByProCode(cpd.getProCode());
            if (setupFin == null) {
                throw new FlowProcessException("融资立项数据不存在~");
            }

            ContractReview contractReview = new ContractReview();
            contractReview.setCodes(IdFactory.getUUIDUpper());
            contractReview.setProCode(cpd.getProCode());
            contractReview.setAddBy(vo.getId());
            contractReview.setAddTime(new Date());
            contractReview.setUptBy(vo.getId());
            contractReview.setUptTime(new Date());
            contractReviewDao.insertByProcess(contractReview);

            //给营销经理发送OA待办
            String oaTitle = UtilTools.getCapOaTitle(proName, CapProcessDetailTypeEnum.PRO_NODE_TYPE12);
            String oaId = oaFlowService.sendOAToDo(oaTitle, vo.getId(), setupFin.getAddBy(), FlowTemplateEnum.CAP_CONTRACT_REVIEW.getSrcBizTable(), contractReview.getId());
            if (StringUtils.isNotBlank(oaId)) {
                capProcessDetailDao.modifyOaIdById(FlowTemplateEnum.CAP_CONTRACT_REVIEW.getSrcBizTable(), oaId, contractReview.getId());
            }
        }
    }

    /**
     * 知会节点处理
     * @param templateId
     * @param thisIdxNo
     * @param processId
     * @param srcBizTable
     * @param srcBizSguid
     * @return
     */
    @Override
    public int notifyProcess(String templateId, Integer thisIdxNo, String processId, String srcBizTable, String srcBizSguid) {
        while (true) {
            //查询下一个节点信息
            int nextNodeIdx = thisIdxNo + 1;
            TemplateNode templateNode = templateNodeService.queryNextIdxsNodes(templateId, nextNodeIdx);
            //如果下个节点为空表示所有节点流程已经走完，返回0
            if (templateNode == null) {
                //修改主表状态为通过
                Process proc = processService.selectByPrimaryKey(processId);
                CapProcessDetail cpd = capProcessDetailDao.queryByProcessId(processId);
                proc.setEndTime(new Date());
                proc.setProcessStatus(ProProcesssStatusEnum.PRO_STATUS9.getCode()); // 9=审批完成
                proc.setIsFeedback("0");
                processService.updateByPrimaryKey(proc);
                // 原业务表审批状态 修改审批状态
                capProcessDetailDao.modifyProcessStatusBySguid(srcBizTable, ProProcesssStatusEnum.PRO_STATUS9.getCode(), null, srcBizSguid);
                //如果是资料报审审批，修改子表-融资报审表状态
                if (StringUtils.equals(CapProcessDetailTypeEnum.PRO_NODE_TYPE5.getNode(), cpd.getFlowNode())) {
                    capProcessDetailDao.modifyFinancingApproval(ProProcesssStatusEnum.PRO_STATUS9.getCode(), cpd.getProCode(), ProProcesssStatusEnum.PRO_STATUS1.getCode());
                }
                //修改项目流程明细表状态
                capProcessDetailDao.modifyProcessStatus(ProProcesssStatusEnum.PRO_STATUS9.getCode(), processId);
                //支付或付款--需要往财务模块--资金支付/收款登记
                savePayOrIncomeBill(cpd.getProCode(), srcBizSguid, srcBizTable);
                return 0;
            }
            //如果下个节点不是知会节点返回传入的节点，继续走审批流程
            if (templateNode.getNodePolicy() != 2) return thisIdxNo;
            //知会节点录入默认审核状态为-我已同意
            ProcessNode notify_next = new ProcessNode();
            notify_next.setAddTime(new Date());
            notify_next.setProcessId(processId);
            notify_next.setNodeIdx(templateNode.getNodeIdx());
            notify_next.setNodeName(templateNode.getNodeName());
            notify_next.setNodePolicy(2);// 权限 知会
            notify_next.setDealUserId(wsFlowProcessService.checkUserId(templateNode.getId()));// 处理人取模板中的审核人
            notify_next.setState("1");// 节点的审批状态为-我已同意
            notify_next.setSrcBizTable(srcBizTable);
            notify_next.setSrcBizSguid(srcBizSguid);
            processNodeService.insert(notify_next);
            //记录当前节点
            thisIdxNo = nextNodeIdx;
        }
    }

    /**
     * 查询对应的处理人真实姓名
     */
    private Operator dealNameOf(String checkUserId) {
        Operator opt = operatorService.selectByPrimaryKey(checkUserId);
        if (opt == null) {
            return new Operator();
        }
        else {
            return opt;
        }
    }

    @Override
    public String checkShowAuditTab(String processId, AuthorizationVO vo) {
        Process proc = processService.selectByPrimaryKey(processId);
        if (proc == null) {
            return "0";
        }
        // 当前索引
        Integer nowIdx = proc.getNowIdx();
        // 查询当前审批流程节点
        ProcessNode procNodeWhere = new ProcessNode();
        procNodeWhere.setProcessId(processId);
        procNodeWhere.setNodeIdx(nowIdx);
        procNodeWhere.setState("-1"); // 未审批
        procNodeWhere.setDealUserId(vo.getId());// 审批人为当前操作人
        List<ProcessNode> queryProcessNodes = processNodeService.selectByEntityWhere(procNodeWhere);
        if (queryProcessNodes == null || queryProcessNodes.size() < 1) {
            return "0";
        }
        return "1";
    }

    @Override
    public String getProCodeById(String tableName, String id) {
        return capProcessDetailDao.queryProCodeById(tableName, id);
    }

    @Override
    public CapProcessDetail queryByProcessId(String processId) {
        return capProcessDetailDao.queryByProcessId(processId);
    }

    @Override
    public List<String> queryFinanceUserIdByProcessId(String processId, String state, String groupId) {
        PostGroup postGroup = postGroupDao.selectByPrimaryKey(groupId);
        if (postGroup == null) return null;
        if (StringUtils.equals("2", postGroup.getRoleType())) {
            //固定人员查询sql
            return capProcessDetailDao.queryFinUserIdByProcIdRoleType2(processId, state, groupId);
        } else {
            return capProcessDetailDao.queryFinanceUserIdByProcessId(processId, state, groupId);
        }
    }

    @Override
    public void modifyOaIdById(String tableName, String oaId, String id) {
        capProcessDetailDao.modifyOaIdById(tableName, oaId, id);
    }

    @Override
    public PageInfo<CapHisProcessDomain> getHisProcessPage(String proCode, ParamPage paramPage) {
        PageHelper.startPage(paramPage.getPage(), paramPage.getLimit());
        List<CapHisProcessDomain> list = capProcessDetailDao.queryHisProcessList(proCode);
        PageInfo<CapHisProcessDomain> pageInfo = new PageInfo<CapHisProcessDomain>(list);
        return pageInfo;
    }

    @Override
    public void modifyDetailJsonById(CapProcessDetail cpd) {
        capProcessDetailDao.modifyDetailJsonById(cpd);
    }

    /**
     * 财务模块，资金支付或收款登记新增数据
     * @param proCode
     * @param bizSguid
     * @param bizTableName
     */
    public void savePayOrIncomeBill(String proCode, String bizSguid, String bizTableName) {
        AuthorizationVO vo = SessionUserUtils.getSessionAttributeForUserDtl();
        if (StringUtils.equals(bizTableName, FlowTemplateEnum.CAP_LOAN_FIN.getSrcBizTable())) {
            //融资放款
            LoanFinVo loanFinVo = loanFinDao.selectById(bizSguid);
            if (loanFinVo == null) throw new FlowProcessException("融资放款数据不存在~");
            IncomeBill incomeBill = incomeBillService.setIncBillInfo(proCode, IncomeSettlementModeEnum.INC_SETT_MODE3,
                    IncomeBillTypeEnum.INCOME_BILL_TYPE2, new BigDecimal(loanFinVo.getApplyAmount()),
                    new BigDecimal(loanFinVo.getActualAmount()), FlowTemplateEnum.CAP_LOAN_FIN, bizSguid, vo);
            incomeBillService.insertSelective(incomeBill);
        } else if (StringUtils.equals(bizTableName, FlowTemplateEnum.CAP_FINANCE_REIMBURSEMENT.getSrcBizTable())) {
            //融资还款
            FinanceReimbursement finReim = financeReimbursementDao.selectByPrimaryKey(bizSguid);
            if (finReim == null) throw new FlowProcessException("融资还款数据不存在~");
            PayBill payBill = payBillService.setPayBillInfo(proCode, IncomeSettlementModeEnum.INC_SETT_MODE3,
                    finReim.getRepayAmt(), finReim.getActRepayAmt(), PayBillTypeEnum.PAY_BILL_TYPE2,
                    FlowTemplateEnum.CAP_FINANCE_REIMBURSEMENT, bizSguid, vo);
            payBillService.insertSelective(payBill);
        } else if (StringUtils.equals(bizTableName, FlowTemplateEnum.CAP_PAY_INTEREST.getSrcBizTable())) {
            //融资付息
            PayInterest payInte = payInterestDao.selectByPrimaryKey(bizSguid);
            if (payInte == null) throw new FlowProcessException("融资付息数据不存在~");
            PayBill payBill = payBillService.setPayBillInfo(proCode, IncomeSettlementModeEnum.INC_SETT_MODE3,
                    payInte.getPayIntAmt(), payInte.getActualPayAmt(), PayBillTypeEnum.PAY_BILL_TYPE3,
                    FlowTemplateEnum.CAP_PAY_INTEREST, bizSguid, vo);
            payBillService.insertSelective(payBill);
        } else if (StringUtils.equals(bizTableName, FlowTemplateEnum.CAP_PAYFEE_APPLY.getSrcBizTable())) {
            PayfeeApply payfeeApply = payfeeApplyDao.selectByPrimaryKey(bizSguid);
            if (payfeeApply == null) throw new FlowProcessException("融资付费申请数据不存在~");
            List<PayfeeApplyInfo> list = payfeeApplyDetailDao.queryDetailById(payfeeApply.getId());
            BigDecimal payTotal = new BigDecimal(0);
            if (list != null && list.size() > 0) {
                for (PayfeeApplyInfo pai : list) {
                    if (pai == null) continue;
                    payTotal = payTotal.add(pai.getPayAmount());
                }
            }
            PayBill payBill = payBillService.setPayBillInfo(proCode, IncomeSettlementModeEnum.INC_SETT_MODE3,
                    payTotal, payfeeApply.getActualPayAmt(), PayBillTypeEnum.PAY_BILL_TYPE4,
                    FlowTemplateEnum.CAP_PAYFEE_APPLY, bizSguid, vo);
            payBillService.insertSelective(payBill);
        }
    }
}
